﻿using System;
using System.Collections;
using System.Data.Common;
using System.Data.OleDb;
using System.Data.OracleClient;
using System.Data.SqlClient;
using System.Threading;
using _5E.Utils.DbHelper.ParameterParser;

namespace _5E.Utils.DbHelper
{
    /// <summary>
    /// 程序说明：数据库基类工厂
    /// 创建作者：ahl
    /// 创建时间：2012-03-26
    /// </summary>
    public class DbFactory
    {
        #region 变量

        private static object s_Mutex = new object();

        private static Type s_DbConnectionType = null;

        private static Type s_DbCommandType = null;

        private static Type s_DbParameterType = null;

        private static Type s_DbDataAdapter = null;

        private static Type s_BaseDbType = null;

        private static Type s_EntityParser = null;

        private static Type s_HashtableParser = null;

        #endregion

        #region 静态属性

        private static string s_ConnectionString = null;
        public static string ConnectionString { set { s_ConnectionString = value; } }

        private static EnumDbType s_DbType = EnumDbType.MsSql;
        public static EnumDbType DbType
        {
            set
            {
                if (s_DbType != value)
                {
                    Monitor.Enter(s_Mutex);
                    s_DbType = value;
                    Init();
                    Monitor.Exit(s_Mutex);
                }
            }
        }

        private static string s_MappingDirectory = null;
        public static string MappingDirectory
        {
            set
            {
                s_MappingDirectory = value;
                if (!s_MappingDirectory.EndsWith("\\"))
                {
                    s_MappingDirectory += "\\";
                }
            }
            get
            {
                if (string.IsNullOrEmpty(s_MappingDirectory))
                {
                    s_MappingDirectory = AppDomain.CurrentDomain.BaseDirectory.Replace("bin\\Debug\\", string.Empty);
                }
                return s_MappingDirectory;
            }
        }

        #endregion

        #region 构造函数

        static DbFactory()
        {
            Init();
        }

        #endregion

        #region 静态方法

        private static void Init()
        {
            SetAdoType();
            CreateBaseDbType();
            CreateParameterParser();
        }

        private static void SetAdoType()
        {
            if (s_DbType == EnumDbType.Oracle)
            {
                s_DbConnectionType = typeof(OracleConnection);
                s_DbCommandType = typeof(OracleCommand);
                s_DbParameterType = typeof(OracleParameter);
                s_DbDataAdapter = typeof(OracleDataAdapter);
            }
            else if (s_DbType == EnumDbType.Access)
            {
                s_DbConnectionType = typeof(OleDbConnection);
                s_DbCommandType = typeof(OleDbCommand);
                s_DbParameterType = typeof(OleDbParameter);
                s_DbDataAdapter = typeof(OleDbDataAdapter);
            }
            else
            {
                s_DbConnectionType = typeof(SqlConnection);
                s_DbCommandType = typeof(SqlCommand);
                s_DbParameterType = typeof(SqlParameter);
                s_DbDataAdapter = typeof(SqlDataAdapter);
            }
        }

        private static void CreateBaseDbType()
        {
            var baseDbGenericArguments = new[] { s_DbConnectionType, s_DbCommandType, s_DbParameterType, s_DbDataAdapter };
            var baseDbGenericType = typeof(BaseDb<,,,>);
            s_BaseDbType = baseDbGenericType.MakeGenericType(baseDbGenericArguments);
        }

        private static void CreateParameterParser()
        {
            var parameterGenericArguments = new[] { s_DbParameterType };
            var entityParserGenericType = typeof(EntityParser<>);
            s_EntityParser = entityParserGenericType.MakeGenericType(parameterGenericArguments);
            var hashtableParserGenericType = typeof(HashtableParser<>);
            s_HashtableParser = hashtableParserGenericType.MakeGenericType(parameterGenericArguments);
        }

        public static IDb<DbConnection, DbCommand, DbParameter, DbDataAdapter> BuildDb()
        {
            var instance = Activator.CreateInstance(s_BaseDbType, s_ConnectionString);
            return instance as IDb<DbConnection, DbCommand, DbParameter, DbDataAdapter>;
        }

        public static IParameterParser<DbParameter> BuildEntityParser(object entity)
        {
            var instance = Activator.CreateInstance(s_EntityParser, entity);
            return instance as IParameterParser<DbParameter>;
        }

        public static IParameterParser<DbParameter> BuildHashtableParser(Hashtable parameters)
        {
            var instance = Activator.CreateInstance(s_HashtableParser, parameters);
            return instance as IParameterParser<DbParameter>;
        }

        #endregion
    }
}
